package wangjg.xuexiban.data;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

import wangjg.commons.io.file.FileIOHelper;
import wangjg.commons.io.file.FilePathHelper;
import wangjg.xuexiban.entity.Card;
import wangjg.xuexiban.entity.CardName;
import wangjg.xuexiban.util.Constant;
import wangjg.xuexiban.util.ResoureUtil;
import android.graphics.Bitmap;
import android.util.Log;

public class CardDAO {
	private String categoryPath;
	private long lastModified;
	private boolean reload = true;
	private List<Card> items = new ArrayList<Card>();
	
	public CardDAO() {
		super();
	}

	public void setCategoryPath(String root) {
		this.categoryPath = root;
	}
	
	int ______________;

	public Card get(Long id){
		int index = id.intValue();
		List<Card> list = this.getList();
		if(list.size()==0){
			return null;
		}
		Card card = this.getList().get(index);
		this.checkCard(card);
		return card;
	}

	public List<Card> getList() {
		if(reload || lastModified==0){
			File file = new File(categoryPath,Constant.DATA_LIST_FILENAME);
			this.items.clear();
			this.load(file);
		}
		return items;
	}

	public int getCount(){
		return this.getList().size();
	}

	public void saveOrUpdate(Card card){
		if(card.getId()!=null){
			Card old = this.get(card.getId());
			this.deleteFile(old, card);
		}
		
		boolean add = false;
		if(card.getId()==null){
			add = true;
			card.setId(Long.valueOf(this.getCount()));
		}
		
		this.copyFile2(card);
		
		if(add){
			this.save(card);
		}else{
			this.update(card);
		}
	}
	
	public void save(Card card){
		this.checkRepeat(card);
		this.items.add(card);
		this.saveListFile();
	}
	
	public void update(Card card){
		this.checkRepeat(card);
		this.items.set(card.getId().intValue(), card);
		this.saveListFile();
	}
	
	private boolean checkRepeat(Card card){
		for(Card card2:this.items){
			for(CardName cn2:card2.getNameList()){
				for(CardName cn: card.getNameList()){
					if(cn2.getName()!=null && cn2.getName().equals(cn.getName())){
						if(card.getId()==null){
							return false;
						}else if(!card.getId().equals(card2.getId())){
							return false;
						}
					}
				}
			}
		}
		return true;
	}
	
	public void delete(int index){
		if(index<0 || index>=this.items.size()){
			return;
		}
		Card card = items.get(index);
		this.deleteFile(card);
		this.items.remove(index);
		this.saveListFile();
	}
	
	public void setReloadFlag() {
		this.reload = true;
	}

	private void copyFile(Card card){
		String dataDir = categoryPath+File.separatorChar+"data";
		File dirFile = new File(dataDir);
		if(dirFile.exists()){
			dirFile.mkdirs();
		}
		String word = null;
		if(card.getNameList()!=null){
			for(CardName cn : card.getNameList()){
				if(word==null||!"中文".equals(cn.getLanguage())){
					word=cn.getName();
				}
				
				if(cn.getSpeech()!=null&&cn.getSpeech().startsWith("/")){
					String ext = FilePathHelper.getExtName(cn.getSpeech());
					String targetFilename = cn.getName()+'.'+ext;
					File source = new File(cn.getSpeech());
					File target = new File(dirFile, targetFilename);
					if(target.exists()){
						targetFilename = cn.getName()+"-"+card.getId()+"-"+System.currentTimeMillis()+'.'+ext;
						target = new File(dirFile, targetFilename);
					}
					if(source.canRead() && !source.equals(target)){
						FileIOHelper.FileToFile(source, target);
						cn.setSpeech(target.getName());
					}
				}
				
			}
		}
		//pic
		if(true){
			String ext = FilePathHelper.getExtName(card.getPicture());
			String picFileName = word+'.'+ext;
			File target = new File(dirFile, picFileName);
			File source = new File(card.getPicture());
			if(target.exists()){
				picFileName = word+"-"+this.getCount()+"-"+System.currentTimeMillis()+'.'+ext;
				target = new File(dirFile, picFileName);
			}
			if(source.canRead() && !source.equals(target)){
				Bitmap bitmap = ResoureUtil.getImageResoure(source.getPath());
				if(bitmap.getWidth()>600||bitmap.getWidth()>500){
					bitmap = ResoureUtil.zoomImg(bitmap, 600, 500);
					ResoureUtil.saveBitmap(bitmap, target.getPath());
				}else{
					FileIOHelper.FileToFile(source, target);			
				}
				card.setPicture(picFileName);
			}
		}
	}


	private void copyFile2(Card card){
		String dataDir = categoryPath+File.separatorChar+"data";
		
		File dirFile = new File(dataDir);
		if(dirFile.exists()){
			dirFile.mkdirs();
		}
		
		String word = null;
		//复制声音
		if(card.getNameList()!=null){
			for(CardName cn : card.getNameList()){
				if(word==null||!"中文".equals(cn.getLanguage())){
					word = cn.getName();
				}
				if(cn.getSpeech()!=null && cn.getSpeech().length()>0){
					String ext = FilePathHelper.getExtName(cn.getSpeech());
					File source = new File(cn.getSpeech());
					File target = new File(dirFile, cn.getName()+'.'+ext);
					
					if(!source.canRead()){
						throw new RuntimeException("文件不可读:"+source.getName());
					}
					
					int n = 1;
					while(target.exists()){
						String targetFilename = cn.getName()+"-"+card.getId()+"-"+(n++)+'.'+ext;
						target = new File(dirFile, targetFilename);
					}
					
					FileIOHelper.FileToFile(source, target);
					cn.setSpeech(target.getName());
				}
			}
		}
		//复制图片
		if(card.getPicture()!=null && card.getPicture().length()>0){
			String ext = FilePathHelper.getExtName(card.getPicture());
			File target = new File(dirFile, word+'.'+ext);
			File source = new File(card.getPicture());
			
			if(!source.canRead()){
				throw new RuntimeException("文件不可读:"+source.getName());
			}
			
			int n = 1;
			while(target.exists()){
				String targetFilename = word +"-"+card.getId()+"-"+(n++)+'.'+ext;
				target = new File(dirFile, targetFilename);
			}
			
			Bitmap bitmap = ResoureUtil.getImageResoure(source.getPath());
			if(bitmap.getWidth()>600||bitmap.getWidth()>500){
				bitmap = ResoureUtil.zoomImg(bitmap, 600, 500);
				ResoureUtil.saveBitmap(bitmap, target.getPath());
			}else{
				FileIOHelper.FileToFile(source, target);			
			}
			card.setPicture(target.getPath());
		}
	}

	private void deleteFile(Card card){
		File categoryDataDir = new File(categoryPath, "data");
		if(card.getPicture()!=null && card.getPicture().startsWith(categoryDataDir.getPath())){
			File file = new File(card.getPicture());
			Log.i(file.getPath()+","+"x",file.exists()+","+file.canWrite());
			file.delete();
		}
		if(card.getVideo()!=null && card.getVideo().startsWith(categoryDataDir.getPath())){
			File file = new File(card.getVideo());
			file.deleteOnExit();
		}
		for(CardName cn:card.getNameList()){
			if(cn.getSpeech()!=null && cn.getSpeech().startsWith(categoryDataDir.getPath())){
				File file = new File(cn.getSpeech());
				file.delete();
			}
		}
	}
	
	private void deleteFile(Card oldCard, Card newCard){
		File categoryDataDir = new File(categoryPath, "data");
		if(oldCard.getPicture()!=null && oldCard.getPicture().startsWith(categoryDataDir.getPath())){
			File file = new File(oldCard.getPicture());
			if(!file.equals(new File(newCard.getPicture()))){
				file.delete();	
			}
		}
		if(oldCard.getVideo()!=null && oldCard.getVideo().startsWith(categoryDataDir.getPath())){
			File file = new File(oldCard.getVideo());
			if(newCard.getVideo()==null || !file.equals(new File(newCard.getVideo()))){
				file.delete();
			}
		}
		label1:
		for(CardName cn:oldCard.getNameList()){
			if(cn.getSpeech()!=null && cn.getSpeech().startsWith(categoryDataDir.getPath())){
				File file = new File(cn.getSpeech());
				for(CardName newCn:newCard.getNameList()){
					if(file.equals(new File(newCn.getSpeech()))){
						continue label1;
					}
				}
				file.delete();
			}
		}
	}

	private void load(File file){
		FileInputStream fis = null;
		try {
			if(!file.exists() || !file.canRead()){
				return;
			}
			fis = new FileInputStream(file);
			InputStreamReader isr = new InputStreamReader(fis,"utf-8");
			BufferedReader br = new BufferedReader(isr);
			Card card = null;
			String line = null;
			while((line=br.readLine())!=null){
				int len = line.length();
				boolean j = line.startsWith("#");
				boolean ne = line.indexOf('=')==-1;
				String[] ss=line.split("=");
				if(len==0||j||ne||line.trim().length()==0||ss.length!=2){
					if(card!=null){
						this.items.add(card);
						card = null;
					}
					continue;
				}
				if(card==null){
					card = new Card();
					card.setId((long)this.items.size());
					card.setNameList(new ArrayList<CardName>());
				}
				String key = ss[0];
				String value = ss[1];
				if("picture".equals(key)){
					card.setPicture(getFullPath(value));
				}else if("video".equals(key)){
					card.setVideo(getFullPath(value));
				}else if("name".equals(key)){
					String[] sss = value.split(",");
					if(sss.length==0){
						continue;
					}
					CardName cn = new CardName();
					if(sss.length>0){
						cn.setLanguage(sss[0]);
					}
					if(sss.length>1){
						cn.setName(sss[1]);
					}
					if(sss.length>2){
						cn.setSpeech(getFullPath(sss[2]));
					}
					card.getNameList().add(cn);
				}
			}
			if(card!=null){
				this.items.add(card);
				card = null;
			}
			lastModified = file.lastModified();
			this.reload = false;
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(fis!=null) fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	protected String getFullPath(String filename){
		if(filename==null)
			return null;
		if(filename.startsWith("/")){
			return filename;
		}
		String path = this.categoryPath + File.separator+"data"+File.separator+filename;
		return path;
	}

	private void saveListFile() {
		File file = new File(categoryPath, Constant.DATA_LIST_FILENAME);
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
			OutputStreamWriter writer = new OutputStreamWriter(fos, "utf-8");
			for (int i = 0; i < items.size(); i++) {
				Card card = items.get(i);
				writer.write(this.getCardString(card));
				writer.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (fos != null)
					fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		this.reload = true;
	}
	
	private void checkCard(Card card){
		if(card.defaultName()==null){
			card.addName(new CardName());
		}
	}
	
	private String getCardString(Card card){
		StringBuilder sb = new StringBuilder();
		sb.append("\n");
		sb.append("picture=");
		append(sb, card.getPicture());
		sb.append("\n");
		if(card.getVideo()!=null){
			sb.append("video=");
			append(sb, card.getVideo());
			sb.append("\n");
		}
		for(CardName cn:card.getNameList()){
			sb.append("name=");
			append(sb, cn.getLanguage());
			sb.append(",");
			append(sb, cn.getName());
			sb.append(",");
			append(sb, cn.getSpeech());
			sb.append("\n");
		}
		return sb.toString();
	}
	
	private void append(StringBuilder sb, Object obj){
		if(obj!=null){
			sb.append(obj);
		}
	}
}
